<?php
/**
 * Cli Server Router PHP内置服务器路由器
 * 版权所有 (c) 2020-2021 上海宙品信息科技有限公司
 *
 * Gitee: <https://gitee.com/zeupin/cli-server-router>
 */

/**
 * PHP内置Web Server的路由脚本
 * https://www.php.net/manual/zh/features.commandline.webserver.php
 * https://gitee.com/zeupin/cli-server-router
 *
 * 注意事项：
 * 1、PHP内置的Web服务器主要用于本地开发和调试，不要用于线上产品环境。
 * 2、在命令行启动这个内置PHP Web Server时，如果指定了一个“PHP路由脚本”（PHP Routing Script），意味着每次请求都会先执行这个“路由脚本”。
 * 3、如果这个路由脚本返回 false ，那么直接返回请求的文件（例如请求静态文件不作任何处理）。
 * 4、如果返回的不是false，那么会把路由文件的输出返回到浏览器。
 * 5、如果请求未指定执行一个“路由脚本”，则默认执行目录内的index.php或者index.html。如果这两个文件都不存在，服务器会返回404错误。
 */
class CliServerRouter
{
    /**
     * 配置
     * [
     *    'baseURI'   => ... ,
     *    'baseDir'   => ... ,
     *    'entryFile' => ... , // 入口文件
     * ]
     */
    protected $conf = [];

    /**
     * 初始化
     *
     * @param string $baseDir 基础目录
     *
     * @return bool
     */
    public function __construct(array $conf = [])
    {
        // 默认设置
        $default = [
            'baseURI'   => "/",
            'baseDir'   => __DIR__,
            'entryFile' => __DIR__ . "/index.php",
        ];

        // 设置
        $this->conf = array_merge($default, $conf);
    }

    /**
     * 开始运行
     * 如果发现请求的文件存在, 返回false
     *
     * @return bool
     */
    public function run()
    {
        // 如果不是php内置的webserver模式，则不进行后面的处理，直接退出
        if (php_sapi_name() != 'cli-server') {
            return false;
        }

        // 解析网址
        $parse_url = parse_url($_SERVER['REQUEST_URI']);

        // 如果URI是一个无法解析的网址, 直接die
        if ($parse_url === false) {
            die("Invalid Request URI.");
        }

        // 从URI中拆解出path
        $uripath = $parse_url['path'];

        // 检查物理文件是否存在
        if (mb_strpos($uripath, $this->conf['baseURI']) === 0) {
            $filepath = $this->conf["baseDir"] . mb_substr($uripath, mb_strlen($this->conf["baseURI"]) + 1);
            if (file_exists($filepath)) {
                // 如果是目录
                if (is_dir($filepath)) {
                    $this->processFolder($filepath);
                }

                // 如果是文件
                if (is_file($filepath)) {
                    return $this->processFile($filepath);
                }
            }
        }

        // 按照网址不存在处理
        $this->processNotExists();
    }

    protected function processFolder($folder)
    {
        // 如果index.html存在
        if (file_exists("$folder/index.html")) {
            include "$folder/index.html";
            exit();
        }

        // 如果index.php存在
        if (file_exists("$folder/index.php")) {
            include "$folder/index.php";
            exit();
        }

        // 按照网址不存在处理
        $this->processNotExists();
        exit();
    }

    protected function processFile($file)
    {
        // 如果是php文件
        if (mb_substr($file, -4) === '.php') {
            include $file;
            exit();
        }

        // 如果是其它文件
        return false;
    }

    protected function processNotExists()
    {
        require $this->conf["entryFile"];
        exit();
    }
}
